package com.longkier.gx_library_springboot.Service;

import com.longkier.gx_library_springboot.repository.UserRepository;
import com.longkier.gx_library_springboot.entity.User;

import com.longkier.gx_library_springboot.utils.RequestUtils;
import lombok.RequiredArgsConstructor;
import org.apache.ibatis.annotations.Param;
import org.jetbrains.annotations.NotNull;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;

import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;

/**
 * 用户服务，处理用户数据控制操作的逻辑。
 */
@Service
@RequiredArgsConstructor
public class UsersService {
    //private static final Logger logger = LoggerFactory.getLogger(UsersService.class);
    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    // 检查用户名是否存在
    /**
     * 检查指定的用户名是否已被占用。
     *
     * @param username 要检查的用户名
     * @return 如果用户名已被占用，返回 true；否则返回 false
     */
    public boolean isUsernameTaken(String username) {
        return userRepository.findByUsername(username).isPresent();
    }
    // 注册用户
    /**
     * 注册新用户。
     * - 对用户密码进行加密。
     * - 生成唯一的卡号。
     * - 设置默认的规则编号、状态、创建时间和更新时间。
     * - 将用户信息保存到数据库。
     *
     * @param user 要注册的用户对象
     */
    public void registerUser(@NotNull User user) {
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setCardNumber(generateUniqueCardNumber());
        user.setStatus(1);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        userRepository.save(user);
    }

    // 更新用户信息
    /**
     * 更新用户信息。
     * - 使用提供的用户对象中的用户名、卡名称和更新时间更新现有用户信息。
     *
     * @param user 包含更新信息的用户对象
     * @return 如果更新成功，返回 true；否则返回 false
     */
    public boolean updateUser(@NotNull User user) {
        return updateUserField(user.getUserId(), existingUser -> {
            existingUser.setUsername(user.getUsername());
            existingUser.setCardName(user.getCardName());
            existingUser.setUpdateTime(LocalDateTime.now());
        });
    }

    // 删除用户
    /**
     * 根据用户 ID 删除用户。
     *
     * @param userId 要删除的用户的 ID
     * @return 如果删除成功，返回 true；否则返回 false
     */
    public boolean deleteUser(Long userId) {
        if (userRepository.existsById(userId)) {
            userRepository.deleteById(userId);
            return true;
        }
        return false;
    }

    /**
     * 批量删除用户。
     *
     * @param userIds 要删除的用户 ID 列表
     * @return 如果删除成功，返回 删除数量；否则返回 false
     */
    @Transactional
    public boolean batchDeleteUsers(@Param("userIds")List<Long> userIds) {
        if (userIds == null || userIds.isEmpty()) {
            return false;
        }
        int deletedCount = userRepository.deleteAllByIdInBatch(userIds);
        return deletedCount == userIds.size();
    }

    /**
     * 根据用户 ID、用户名或卡号查找用户信息。
     *
     * @param userId     用户 ID（可选）
     * @param username   用户名（可选）
     * @param cardNumber 卡号（可选）
     * @return 用户对象（如果存在），否则返回 null
     */
    public User getUserInfo(Long userId, String username, String cardNumber) {
        if (userId != null) {
            return userRepository.findById(userId).orElse(null);
        }
        if (username != null && !username.isEmpty()) {
            return userRepository.findByUsername(username).orElse(null);
        }
        if (cardNumber != null) {
            return userRepository.findByCardNumber(cardNumber).orElse(null);
        }
        return null;
    }

    /**
     * 分页获取用户列表。
     *
     * @param page 当前页码（从 0 开始）
     * @param size 每页大小
     * @param status 用户状态（可选）
     * @param username 用户名（可选）
     * @param cardName 卡名称（可选）
     * @param cardNumber 卡号（可选）
     * @return 用户分页对象
     */
    public Page<User> getUsersServices(int page, int size, Integer status,
                                       String username,
                                       String cardName,
                                       String cardNumber) {
    Pageable pageable = PageRequest.of(page, size);
    Page<User> usersPage = userRepository.findByCriteria(status, username, cardName, cardNumber, pageable);
    // 隐藏每个用户的密码
    usersPage.getContent().forEach(user -> user.setPassword(null));
    return usersPage;
}

    // 通用的用户字段更新方法
    /**
     * 更新用户字段。
     * - 根据用户 ID 查找用户。
     * - 如果用户存在，使用提供的 Consumer 更新用户字段。
     * - 保存更新后的用户信息。
     *
     * @param userId       用户 ID
     * @param fieldUpdater 用于更新用户字段的 Consumer
     * @return 如果更新成功，返回 true；否则返回 false
     */
    private boolean updateUserField(Long userId, Consumer<User> fieldUpdater) {
        Optional<User> optionalUser = userRepository.findById(userId);
        if (optionalUser.isPresent()) {
            User user = optionalUser.get();
            fieldUpdater.accept(user);
            userRepository.save(user);
            return true;
        }
        return false;
    }

    // 修改用户密码
    /**
     * 修改用户密码。
     * - 如果新密码不为空，则更新密码。
     * - 更新用户信息并保存到数据库。
     *
     * @param userId      用户 ID
     * @param newPassword 新密码
     * @return 如果更新成功，返回 true；否则返回 false
     */
    public boolean updatePasswordAndStatus(Long userId, String newPassword) {
        return updateUserField(userId, user -> {
            if (newPassword != null && !newPassword.isEmpty()) {
                user.setPassword(passwordEncoder.encode(newPassword));
            }
            user.setUpdateTime(LocalDateTime.now());
        });
    }

    // 验证现有密码并修改用户密码
    /**
     * 验证现有密码并修改用户密码。
     * - 根据用户 ID 查找用户。
     * - 如果用户存在且现有密码匹配，则更新密码。
     * - 更新用户信息并保存到数据库。
     *
     * @param userId         用户 ID
     * @param currentPassword 现有密码
     * @param newPassword     新密码
     * @return 如果验证成功并更新密码，返回 true；否则返回 false
     */
    public boolean validateAndUpdatePassword(Long userId, String currentPassword, String newPassword) {
        Optional<User> optionalUser = userRepository.findById(userId);
        if (optionalUser.isPresent()) {
            User user = optionalUser.get();
            if (passwordEncoder.matches(currentPassword, user.getPassword())) {
                user.setPassword(passwordEncoder.encode(newPassword));
                user.setUpdateTime(LocalDateTime.now());
                userRepository.save(user);
                return true;
            }
        }
        return false; // 用户不存在或密码不匹配
    }



    /**
     * 批量设置用户状态。
     *
     * @param userIds 要更新的用户 ID 列表
     * @param status  新的状态
     * @return 如果更新成功，返回 true；否则返回 false
     */
    public boolean batchUpdateStatus(@Param("userIds,status")List<Long> userIds, Integer status) {
        List<User> users = userRepository.findAllById(userIds);
        if (users.isEmpty()) {
            return false;
        }
        users.forEach(user -> {
            user.setStatus(status);
            user.setUpdateTime(LocalDateTime.now());
        });
        userRepository.saveAll(users);
        return true;
    }

    // 随机生成唯一卡号
    /**
     * 生成唯一的卡号。
     * - 生成随机卡号，确保其在数据库中唯一。
     *
     * @return 唯一的卡号
     */
    private String generateUniqueCardNumber() {
        String cardNumber;
        do {
            cardNumber = RequestUtils.generateRandom11Number();
        } while (userRepository.existsByCardNumber(cardNumber));
        return cardNumber;
    }


}
